<?php

/**
 * Radcodes - SocialEngine Module
 *
 * @category   Application_Extensions
 * @package    Badge
 * @copyright  Copyright (c) 2009-2010 Radcodes LLC (http://www.radcodes.com)
 * @license    http://www.radcodes.com/license/
 * @version    $Id$
 * @author     Vincent Van <vincent@radcodes.com>
 */

class Badge_Api_Core extends Core_Api_Abstract {
	const IMAGE_WIDTH = 720;
	const IMAGE_HEIGHT = 720;
	
	const THUMB_WIDTH = 140;
	const THUMB_HEIGHT = 160;
	
	public function getCategories() {
		$table = $this->api ()->getDbtable ( 'categories', 'badge' );
		$categories = $table->fetchAll ( $table->select ()->order ( 'order' ) );
		
		return $categories;
	}
	
	public function getCategory($category_id) {
		static $categories = array ();
		
		if (! isset ( $categories [$category_id] )) {
			$categories [$category_id] = Engine_Api::_ ()->getDbtable ( 'categories', 'badge' )->find ( $category_id )->current ();
		}
		
		return $categories [$category_id];
	}
	
	public function convertCategoriesToArray($categories) {
		$categories_prepared = array ();
		foreach ( $categories as $category ) {
			$categories_prepared [$category->category_id] = $category->category_name;
		}
		return $categories_prepared;
	}
	
	public function getBadgesAsSubOptions($type = null) {
		$categories = $this->getCategories ();
		
		foreach ( $this->getBadgeTable ()->fetchAll () as $badge ) {
			if ($type !== null && ! $badge->isMembershipType ( $type )) {
				continue;
			}
			$cs [$badge->category_id] [$badge->getIdentity ()] = $badge->getTitle ();
		}
		
		$options = array ();
		foreach ( $categories as $category ) {
			if (count ( $cs [$category->getIdentity ()] )) {
				$options [$category->getTitle ()] = $cs [$category->getIdentity ()];
			}
		}
		
		return $options;
	}
	
	public function getBadge($badge_id) {
		static $badges;
		if (! isset ( $badges [$badge_id] )) {
			$badges [$badge_id] = $this->getBadgeTable ()->find ( $badge_id )->current ();
		}
		return $badges [$badge_id];
	}
	
	/**
	 * Gets a paginator for badges
	 *
	 * @param Core_Model_Item_Abstract $user The user to get the messages for
	 * @return Zend_Paginator
	 */
	public function getBadgesPaginator($params = array(), $options = null) {
		$paginator = Zend_Paginator::factory ( $this->getBadgesSelect ( $params, $options ) );
		if (! empty ( $params ['page'] )) {
			$paginator->setCurrentPageNumber ( $params ['page'] );
		}
		if (! empty ( $params ['limit'] )) {
			$paginator->setItemCountPerPage ( $params ['limit'] );
		}
		return $paginator;
	}
	
	/**
	 * Gets a select object for the user's badge entries
	 *
	 * @param Core_Model_Item_Abstract $user The user to get the messages for
	 * @return Zend_Db_Table_Select
	 */
	public function getBadgesSelect($params = array(), $options = null) {
		$table = $this->getBadgeTable ();
		$rName = $table->info ( 'name' );
		
		$select = $table->select ();
		
		if (! empty ( $params ['keyword'] )) {
			$select->where ( $rName . ".title LIKE ? OR " . $rName . ".body LIKE ? OR " . $rName . ".description LIKE ?", '%' . $params ['keyword'] . '%' );
		}
		
		if (isset ( $params ['search'] )) {
			$select->where ( $rName . ".search = ?", $params ['search'] ? 1 : 0 );
		}
		
		if (! empty ( $params ['category'] )) {
			$category_id = ($params ['category'] instanceof Badge_Model_Category) ? $params ['category']->getIdentity () : $params ['category'];
			
			$select->where ( $rName . ".category_id = ?", $category_id );
		}
		
		if (! empty ( $params ['membership_type'] )) {
			$select->where ( $rName . ".membership_type = ?", $params ['membership_type'] );
		}
		
		if (isset ( $params ['filter_profile_photo'] )) {
			// no photo .. only select one that does not care about photo
			if (! $params ['filter_profile_photo']) {
				$select->where ( $rName . ".user_profile_photo = 0" );
			}
		
		// has photo .. select care/not care about photo => hence ignore this
		}
		if (isset ( $params ['filter_view_count'] )) {
			$select->where ( $rName . ".user_view_count <= ?", $params ['filter_view_count'] );
		}
		if (isset ( $params ['filter_invites_used'] )) {
			$select->where ( $rName . ".user_invites_used <= ?", $params ['filter_invites_used'] );
		}
		
		if (isset ( $params ['filter_account_age'] )) {
			$account_age = (time () - strtotime ( $params ['filter_account_age'] )) / 86400;
			$select->where ( $rName . ".user_account_age = 0 OR $rName.user_account_age <= ?", $account_age );
		}
		
		if (isset ( $params ['filter_login_days'] )) {
			if (empty ( $params ['filter_login_days'] )) {
				$select->where ( $rName . ".user_login_days = 0" );
			} else {
				$login_days = (time () - strtotime ( $params ['filter_login_days'] )) / 86400;
				$select->where ( $rName . ".user_login_days = 0 OR $rName.user_login_days >= ?", $login_days );
			}
		}
		
		if (isset ( $params ['filter_level_id'] )) {
			$level_condition = $this->generateFindInSetQueryPart ( "$rName.user_level_ids", $params ['filter_level_id'] );
			$select->where ( "$rName.user_level_settings = 0 OR ($level_condition)" );
		}
		if (isset ( $params ['filter_network_id'] )) {
			$network_condition = $this->generateFindInSetQueryPart ( "$rName.user_network_ids", $params ['filter_network_id'] );
			$select->where ( "$rName.user_network_settings = 0 OR ($network_condition)" );
		}
		if (isset ( $params ['filter_profile_id'] )) {
			$profile_condition = $this->generateFindInSetQueryPart ( "$rName.user_profile_ids", $params ['filter_profile_id'] );
			$select->where ( "$rName.user_profile_settings = 0 OR ($profile_condition)" );
		}
		
		if (empty ( $params ['order'] )) {
			$params ['order'] = 'recent';
		}
		if (isset ( $params ['order'] )) {
			switch ($params ['order']) {
				case 'random' :
					$order_expr = new Zend_Db_Expr ( 'RAND()' );
					break;
				case 'recent' :
					$order_expr = $rName . ".creation_date DESC";
					break;
				case 'mostcommented' :
					$order_expr = $rName . ".comment_count DESC";
					break;
				case 'mostliked' :
					$order_expr = $rName . ".like_count DESC";
					break;
				case 'mostviewed' :
					$order_expr = $rName . ".view_count DESC";
					break;
				case 'alphabet' :
					$order_expr = $rName . ".title ASC";
					break;
				case 'ranking' :
					$order_expr = $rName . ".rank ASC";
					break;
				default :
					$order_expr = ! empty ( $params ['order'] ) ? $params ['order'] : $rName . '.creation_date DESC';
					
					if (! empty ( $params ['order_direction'] )) {
						$order_expr .= " " . $params ['order_direction'];
					}
					
					unset ( $params ['order'] );
			}
			
			$select->order ( $order_expr );
			unset ( $params ['order'] );
		}
		
		//echo $select->__toString();
		

		return $select;
	}
	
	protected function generateFindInSetQueryPart($column, $values) {
		if (! is_array ( $values )) {
			$values = array ($values );
		}
		
		$cs = array ();
		foreach ( $values as $value ) {
			$cs [] = "FIND_IN_SET('$value', $column)";
		}
		
		return join ( " OR ", $cs );
	}
	
	public function getUserMappingBadges($user, $params = array()) {
		$user = Engine_Api::_ ()->user ()->getUser ( $user );
		
		$profile_id = $this->getUserProfileId ( $user );
		
		$networkd_ids = $this->getUserNetworkIds ( $user );
		if (empty ( $networkd_ids ))
			$networkd_ids = array (0 );
		
		$params = array_merge ( array ('membership_type' => Badge_Model_Badge::MEMBERSHIP_TYPE_MAPPING, 

		'filter_profile_photo' => $user->photo_id, 

		'filter_view_count' => $user->view_count, 'filter_invites_used' => $user->invites_used, 

		'filter_account_age' => $user->creation_date, 'filter_login_days' => $user->lastlogin_date, 

		'filter_level_id' => $user->level_id, 'filter_profile_id' => $profile_id, 'filter_network_id' => $networkd_ids, 'order' => 'ranking' ), $params );
		
		$badges = $this->getBadgeTable ()->fetchAll ( $this->getBadgesSelect ( $params ) );
		
		return $badges;
	}
	
	protected function getUserProfileId($user) {
		$user = Engine_Api::_ ()->user ()->getUser ( $user );
		
		$profile_id = 0;
		
		$fieldsByAlias = Engine_Api::_ ()->fields ()->getFieldsObjectsByAlias ( $user, 'profile_type' );
		
		if (! empty ( $fieldsByAlias ['profile_type'] )) {
			$optionId = $fieldsByAlias ['profile_type']->getValue ( $user );
			if ($optionId) {
				$optionObj = Engine_Api::_ ()->fields ()->getFieldsOptions ( $user )->getRowMatching ( 'option_id', $optionId->value );
				
				//$optionId->field_id = 1;
				//echo " field_id=";
				//print_r($optionId->field_id);  
				

				if ($optionObj) {
					$profile_id = $optionObj->option_id;
				
		//echo " option_id=";
				//print_r($optionObj->option_id);
				//$this->view->memberType = $optionObj->label;
				}
			}
		}
		
		return $profile_id;
	}
	
	protected function getUserNetworkIds($user) {
		$user = Engine_Api::_ ()->user ()->getUser ( $user );
		$select = Engine_Api::_ ()->getDbtable ( 'membership', 'network' )->getMembershipsOfSelect ( $user )->where ( 'hide = ?', 0 );
		$networks = Engine_Api::_ ()->getDbtable ( 'networks', 'network' )->fetchAll ( $select );
		
		$ids = array ();
		
		if (count ( $networks )) {
			foreach ( $networks as $network ) {
				$ids [] = $network->getIdentity ();
			}
		}
		
		return $ids;
	}
	
	public function countUserActiveAwards($user) {
		$params = array ('user' => $user, 'active' => true );
		$paginator = $this->getAwardsPaginator ( $params );
		return $paginator->getTotalItemCount ();
	}
	
	/**
	 * Gets a paginator for awards
	 *
	 * @param array $params
	 * @return Zend_Paginator
	 */
	public function getAwardsPaginator($params = array()) {
		$paginator = Zend_Paginator::factory ( $this->getAwardsSelect ( $params ) );
		if (! empty ( $params ['page'] )) {
			$paginator->setCurrentPageNumber ( $params ['page'] );
		}
		if (! empty ( $params ['limit'] )) {
			$paginator->setItemCountPerPage ( $params ['limit'] );
		}
		return $paginator;
	}
	
	/**
	 * Gets a select object for the award entries
	 *
	 * @return Zend_Db_Table_Select
	 */
	public function getAwardsSelect($params = array()) {
		$table = $this->getAwardTable ();
		$rName = $table->info ( 'name' );
		
		$select = $table->select ()->from ( $rName );
		
		if (isset ( $params ['exclude_award_ids'] ) && count ( $params ['exclude_award_ids'] )) {
			$select->where ( $rName . ".award_id NOT IN (?)", $params ['exclude_award_ids'] );
		}
		
		if (! empty ( $params ['keyword'] )) {
			$select->where ( $rName . ".title LIKE ? OR " . $rName . ".body LIKE ? OR " . $rName . ".description LIKE ?", '%' . $params ['keyword'] . '%' );
		}
		
		if (isset ( $params ['search'] )) {
			$select->where ( $rName . ".search = ?", $params ['search'] ? 1 : 0 );
		}
		
		if (! empty ( $params ['badge'] )) {
			$badge_id = ($params ['badge'] instanceof Badge_Model_Badge) ? $params ['badge']->getIdentity () : $params ['badge'];
			
			$select->where ( $rName . ".badge_id = ?", $badge_id );
		}
		
		if (! empty ( $params ['user'] )) {
			$user = Engine_Api::_ ()->user ()->getUser ( $params ['user'] );
			$select->where ( $rName . ".user_id = ?", $user->getIdentity () );
		}
		
		if (isset ( $params ['active'] )) {
			$today_date = date ( "Y-m-d H:i:s" );
			
			// non-expired - active
			if ($params ['active']) {
				$select->where ( "$rName.end_settings = 0 OR ($rName.end_settings = 1 and $rName.end_time > ?)", $today_date );
			} // expired
			else {
				$select->where ( "$rName.end_settings = 1 and $rName.end_time < ?", $today_date );
			}
		}
		
		if (isset ( $params ['featured'] ) && strlen ( $params ['featured'] )) {
			$select->where ( "$rName.featured = ?", $params ['featured'] ? 1 : 0 );
		}
		
		$userTableName = Engine_Api::_ ()->getItemTable ( 'user' )->info ( 'name' );
		$select->join ( $userTableName, "`{$userTableName}`.`user_id` = `{$rName}`.`user_id`", null );
		
		$badgeTableName = $this->getBadgeTable ()->info ( 'name' );
		$select->join ( $badgeTableName, "`{$badgeTableName}`.`badge_id` = `{$rName}`.`badge_id`", null );
		
		$select->where ( $badgeTableName . ".membership_type = ?", Badge_Model_Badge::MEMBERSHIP_TYPE_AWARD );
		
		if (isset ( $params ['member_profile_display'] )) {
			$select->where ( "$badgeTableName.member_profile_display = ?", $params ['member_profile_display'] ? 1 : 0 );
		}
		
		if (empty ( $params ['order'] )) {
			$params ['order'] = 'recent';
		}
		if (isset ( $params ['order'] )) {
			switch ($params ['order']) {
				case 'random' :
					$order_expr = new Zend_Db_Expr ( 'RAND()' );
					break;
				case 'recent' :
					$order_expr = $rName . ".creation_date DESC";
					break;
				case 'mostcommented' :
					$order_expr = $rName . ".comment_count DESC";
					break;
				case 'mostliked' :
					$order_expr = $rName . ".like_count DESC";
					break;
				case 'mostviewed' :
					$order_expr = $rName . ".view_count DESC";
					break;
				case 'alphabet' :
					$order_expr = $rName . ".title ASC";
					break;
				case 'ranking' :
					$order_expr = $rName . ".rank ASC";
					break;
				default :
					$order_expr = ! empty ( $params ['order'] ) ? $params ['order'] : $rName . '.creation_date DESC';
					
					if (! empty ( $params ['order_direction'] )) {
						$order_expr .= " " . $params ['order_direction'];
					}
					
					unset ( $params ['order'] );
			}
			
			$select->order ( $order_expr );
			unset ( $params ['order'] );
		}
		
		return $select;
	}
	
	/**
	 * Gets a paginator for requests
	 *
	 * @param array $params
	 * @return Zend_Paginator
	 */
	public function getRequestsPaginator($params = array()) {
		$paginator = Zend_Paginator::factory ( $this->getRequestsSelect ( $params ) );
		if (! empty ( $params ['page'] )) {
			$paginator->setCurrentPageNumber ( $params ['page'] );
		}
		if (! empty ( $params ['limit'] )) {
			$paginator->setItemCountPerPage ( $params ['limit'] );
		}
		return $paginator;
	}
	
	/**
	 * Gets a select object for the request entries
	 *
	 * @return Zend_Db_Table_Select
	 */
	public function getRequestsSelect($params = array()) {
		$table = $this->getRequestTable ();
		$rName = $table->info ( 'name' );
		
		$select = $table->select ()->from ( $rName );
		
		if (isset ( $params ['exclude_request_ids'] ) && count ( $params ['exclude_request_ids'] )) {
			$select->where ( $rName . ".request_id NOT IN (?)", $params ['exclude_request_ids'] );
		}
		
		if (! empty ( $params ['keyword'] )) {
			$select->where ( $rName . ".description LIKE ?", '%' . $params ['keyword'] . '%' );
		}
		
		if (! empty ( $params ['status'] )) {
			$select->where ( $rName . ".status = ?", $params ['status'] );
		}
		
		if (! empty ( $params ['badge'] )) {
			$badge_id = ($params ['badge'] instanceof Badge_Model_Badge) ? $params ['badge']->getIdentity () : $params ['badge'];
			
			$select->where ( $rName . ".badge_id = ?", $badge_id );
		}
		
		if (! empty ( $params ['user'] )) {
			$user = Engine_Api::_ ()->user ()->getUser ( $params ['user'] );
			$select->where ( $rName . ".user_id = ?", $user->getIdentity () );
		}
		
		$userTableName = Engine_Api::_ ()->getItemTable ( 'user' )->info ( 'name' );
		$select->join ( $userTableName, "`{$userTableName}`.`user_id` = `{$rName}`.`user_id`", null );
		
		$badgeTableName = $this->getBadgeTable ()->info ( 'name' );
		$select->join ( $badgeTableName, "`{$badgeTableName}`.`badge_id` = `{$rName}`.`badge_id`", null );
		
		if (empty ( $params ['order'] )) {
			$params ['order'] = 'recent';
		}
		if (isset ( $params ['order'] )) {
			switch ($params ['order']) {
				case 'random' :
					$order_expr = new Zend_Db_Expr ( 'RAND()' );
					break;
				case 'recent' :
					$order_expr = $rName . ".creation_date DESC";
					break;
				
				default :
					$order_expr = ! empty ( $params ['order'] ) ? $params ['order'] : $rName . '.creation_date DESC';
					
					if (! empty ( $params ['order_direction'] )) {
						$order_expr .= " " . $params ['order_direction'];
					}
					
					unset ( $params ['order'] );
			}
			
			$select->order ( $order_expr );
			unset ( $params ['order'] );
		}
		
		return $select;
	}
	
	public function filterEmptyParams($values) {
		foreach ( $values as $key => $value ) {
			if (is_array ( $value )) {
				foreach ( $value as $value_k => $value_v ) {
					if (! strlen ( $value_v )) {
						unset ( $value [$value_k] );
					}
				}
			}
			
			if (is_array ( $value ) && count ( $value ) == 0) {
				unset ( $values [$key] );
			} else if (! is_array ( $value ) && ! strlen ( $value )) {
				unset ( $values [$key] );
			}
		}
		
		return $values;
	}
	
	/***
	 * @return Badge_Model_DbTable_Badges
	 */
	public function getBadgeTable() {
		return Engine_Api::_ ()->getDbtable ( 'badges', 'badge' );
	}
	
	/**
	 * @return Badge_Model_DbTable_Awards
	 */
	public function getAwardTable() {
		return Engine_Api::_ ()->getDbtable ( 'awards', 'badge' );
	}
	
	/**
	 * @return Badge_Model_DbTable_Requests
	 */
	public function getRequestTable() {
		return Engine_Api::_ ()->getDbtable ( 'requests', 'badge' );
	}
	
	public function getMemberLevelArray() {
		$level_ids = array ();
		foreach ( Engine_Api::_ ()->getDbtable ( 'levels', 'authorization' )->fetchAll () as $level ) {
			$level_ids [$level->getIdentity ()] = $level->getTitle ();
		}
		return $level_ids;
	}
	
	public function getNetworkArray() {
		$network_options = array ();
		foreach ( Engine_Api::_ ()->getDbtable ( 'networks', 'network' )->fetchAll () as $network ) {
			$network_options [$network->getIdentity ()] = $network->getTitle ();
		}
		
		return $network_options;
	}
	
	public function getProfileTypeArray() {
		$mapData = Engine_Api::_ ()->getApi ( 'core', 'fields' )->getFieldsMaps ( 'user' );
		$optionsData = Engine_Api::_ ()->getApi ( 'core', 'fields' )->getFieldsOptions ( 'user' );
		
		// Get top level fields
		$topLevelMaps = $mapData->getRowsMatching ( array ('field_id' => 0, 'option_id' => 0 ) );
		$topLevelFields = array ();
		foreach ( $topLevelMaps as $map ) {
			$field = $map->getChild ();
			$topLevelFields [$field->field_id] = $field;
		}
		
		if (count ( $topLevelFields ) > 1) {
			throw new Engine_Exception ( 'Only one top level field is currently allowed' );
		}
		$topLevelField = array_shift ( $topLevelFields );
		// Only allow the "profile_type" field to be a top level field (for now)
		if ($topLevelField->type !== 'profile_type') {
			throw new Engine_Exception ( 'Only profile_type can be a top level field' );
		}
		
		// Get top level options
		$topLevelOptions = array ();
		foreach ( $optionsData->getRowsMatching ( 'field_id', $topLevelField->field_id ) as $option ) {
			$topLevelOptions [$option->option_id] = $option->label;
		}
		
		return $topLevelOptions;
	}
}